using System.Collections.Generic;
using UseCaseManager.BO;
using NUnit.Framework;

namespace UseCaseManager.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for Project objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for Project.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestProject
    {
        [TestFixtureSetUp]
        public void SetupTestFixture()
        {
            //------------------------------------------------------------
            // Use this list to ignore generated tests that are failing
            // due to a unique condition in your application.
            // Remember to reimplement the test here.
            //------------------------------------------------------------
            //_ignoreList.Add("TestMethodName", "Reason for ignoring it");
            base.TestFixtureSetup();
        }

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string actualString = project.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(project.ProjectName, actualString);
        }

        [Test]
        public void Test_Calculate_PointsAssigned_TwoReleases()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.GetComplexSavedProject();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(project.PointsAssigned);
            //---------------Execute Test ----------------------
            int totalPoints = project.PointsAssigned;
            //---------------Test Result -----------------------
            int expectedTotalPoints = (project.Releases[0].PointsAssigned + project.Releases[1].PointsAssigned);
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_PointsBaseline_TwoReleases()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.GetComplexSavedProject();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(project.PointsBaseline);
            //---------------Execute Test ----------------------
            int totalPoints = project.PointsBaseline;
            //---------------Test Result -----------------------
            int expectedTotalPoints = (project.Releases[0].PointsBaseline + project.Releases[1].PointsBaseline);
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_PointsCompleted()
        {
            //---------------Set up test -----------------------
            Project project = TestUtilsProject.GetComplexSavedProject();
            int expectedPointsCompleted = 0;
            foreach (Release release in project.Releases)
            {
                foreach (Drop drop in release.Drops)
                {
                    foreach (UseCase useCase in drop.UseCases)
                    {
                        useCase.CompletedInDropID = drop.DropID;
                        expectedPointsCompleted += useCase.PointsAssigned.Value;
                    }
                }
            }
            //---------------Assert pre conditions -------------
            Assert.IsNotNull(project.PointsCompleted);
            Assert.AreNotEqual(0, expectedPointsCompleted);
            //---------------Execute Test ----------------------
            int pointsCompleted = project.PointsCompleted;
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedPointsCompleted, pointsCompleted);
        }

        [Test]
        public void Test_Calculate_PointsAssignedRemaining_OneRelease()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            int expectedTotalAssignedPoints;
            const int expectedNumberOfUseCases = 5;
            const int expectedNumberOfDrops = 1;
            const int expectedNumberOfReleases = 1;
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases
                (expectedNumberOfUseCases, out expectedTotalAssignedPoints);
            release.Drops.Add(drop);
            project.Releases.Add(release);
            int expectedAssignedPointsRemaining = project.PointsAssigned - release.PointsAssigned;
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCases, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            Assert.AreEqual(expectedNumberOfReleases,project.Releases.Count);
            Assert.AreEqual(0, expectedAssignedPointsRemaining);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsAssignedRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedAssignedPointsRemaining, release.CumulativePointsAssignedRemaining);
        }

        [Test]
        public void Test_SetBaseline_NoPreviousBaseline_OneInstanceOfEachClass()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            Drop drop = TestUtilsDrop.CreateUnsavedValidDrop();
            UseCase useCase = TestUtilsUseCase.CreateUnsavedValidUseCase();
            int assignedPoints = TestUtils.GetRandomInt(0, 50);
            useCase.PointsAssigned = assignedPoints;
            drop.UseCases.Add(useCase);
            release.Drops.Add(drop);
            project.Releases.Add(release);
            project.Save();
            //---------------Assert Precondition----------------
            const int expectedCount = 1;
            Assert.AreEqual(expectedCount, project.Releases.Count);
            Assert.AreEqual(expectedCount, release.Drops.Count);
            Assert.AreEqual(expectedCount, drop.UseCases.Count);
            //---------------Execute Test ----------------------
            project.SetBaseline();
            //---------------Test Result -----------------------
            Assert.AreEqual(useCase.PointsAssigned, useCase.PointsBaseline);
        }

        [Test]
        public void Test_SetBaseline_NoPreviousBaseline_ComplexCase()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateSavedProject();
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases(2);
            release.Drops.Add(drop);
            project.Releases.Add(release);
            project.Save();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            project.SetBaseline();
            //---------------Test Result -----------------------
            Assert.AreEqual(drop.UseCases[0].PointsAssigned, drop.UseCases[0].PointsBaseline);
            Assert.AreEqual(drop.UseCases[1].PointsAssigned, drop.UseCases[1].PointsBaseline);
        }

        [Test]
        public void Test_SetBaseline_HasPreviousBaseline_OneInstanceOfEachClass()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            Drop drop = TestUtilsDrop.CreateUnsavedValidDrop();
            UseCase useCase = TestUtilsUseCase.CreateUnsavedValidUseCase();
            int assignedPoints = TestUtils.GetRandomInt(0, 50);
            useCase.PointsAssigned = assignedPoints;
            drop.UseCases.Add(useCase);
            release.Drops.Add(drop);
            project.Releases.Add(release);
            project.Save();
            project.SetBaseline();
            project.Save();
            //---------------Assert Precondition----------------
            const int expectedCount = 1;
            Assert.AreEqual(expectedCount, project.Releases.Count);
            Assert.AreEqual(expectedCount, release.Drops.Count);
            Assert.AreEqual(expectedCount, drop.UseCases.Count);
            //---------------Execute Test ----------------------
            useCase.PointsAssigned = assignedPoints - 5;
            project.SetBaseline();
            //---------------Test Result -----------------------
            Assert.AreEqual(useCase.PointsAssigned, useCase.PointsBaseline);
        }

        /// <summary>
        /// This test proves that the baseline points are not changing everytime 
        /// the assigned points change
        /// </summary>
        [Test]
        public void Test_SetBaseline_HasPreviousBaseline_IsNotChangingPointsAssigned()
        {
            //---------------Set up test pack-------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            Drop drop = TestUtilsDrop.CreateUnsavedValidDrop();
            UseCase useCase = TestUtilsUseCase.CreateUnsavedValidUseCase();
            int assignedPoints = TestUtils.GetRandomInt(0, 50);
            useCase.PointsAssigned = assignedPoints;
            drop.UseCases.Add(useCase);
            release.Drops.Add(drop);
            project.Releases.Add(release);
            project.Save();
            //---------------Assert Precondition----------------
            const int expectedCount = 1;
            Assert.AreEqual(expectedCount, project.Releases.Count);
            Assert.AreEqual(expectedCount, release.Drops.Count);
            Assert.AreEqual(expectedCount, drop.UseCases.Count);
            //---------------Execute Test ----------------------
            project.SetBaseline();
            useCase.PointsAssigned = assignedPoints - 5;
            //---------------Test Result -----------------------
            Assert.AreNotEqual(useCase.PointsAssigned, useCase.PointsBaseline);
            Assert.AreNotEqual(project.PointsAssigned, project.PointsBaseline);
        }
    }
}